package com.hejjon.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hejjon.bean.BasicTypeParam;
import com.hejjon.core.bean.TreeNode;
import com.hejjon.core.domain.entity.BasicType;
import com.hejjon.core.domain.entity.FeatureCategory;
import com.hejjon.core.domain.vo.BasicTypeVO;
import com.hejjon.core.enumer.DeleteFlagEnum;
import com.hejjon.core.enumer.FeatureKindEnum;
import com.hejjon.core.enumer.JdbcTypeEnum;
import com.hejjon.core.exception.BusinessException;
import com.hejjon.core.utils.StrUtil;
import com.hejjon.core.utils.TreeBuilder;
import com.hejjon.mapper.BasicTypeMapper;
import com.hejjon.service.IBasicTypeService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author cs
 * @since 2025-03-06
 */
@Service
public class BasicTypeServiceImpl extends ServiceImpl<BasicTypeMapper, BasicType> implements IBasicTypeService {


    @Resource
    private FeatureCategoryServiceImpl featureCategoryService;

    @Override
    public boolean create(BasicType basicType) {

        String categoryId = basicType.getCategoryId();
        if (StringUtils.isEmpty(categoryId)) {
            throw new BusinessException("类型分类不可为空");
        }

        if (StringUtils.isEmpty(basicType.getJdbcTypeCode())) {
            throw new BusinessException("JDBC类型码不可为空");
        }

        String name = basicType.getName();
        String text = basicType.getText();

        LambdaQueryWrapper<BasicType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BasicType::getDeleteFlag,DeleteFlagEnum.NO.getCode());
        wrapper.eq(BasicType::getName, name)
                .or()
                .eq(BasicType::getText, text);
        boolean exists = exists(wrapper);
        if (exists) {
            throw new BusinessException("类型名称或显示名称已存在!");
        }
        basicType.setDeleteFlag(DeleteFlagEnum.NO.getCode());
        basicType.setId(StrUtil.getUUID());
        basicType.setCreateBy("admin");
        basicType.setCreateTime(LocalDateTime.now());

        return super.save(basicType);
    }

    @Override
    public List<BasicTypeVO> listByCategoryId(String categoryId) {
        return baseMapper.selectByCategoryId(categoryId);
    }

    @Override
    public List<BasicTypeVO> listByCategoryIdAndParams(String categoryId, BasicTypeParam param) {
        List<BasicTypeVO> basicTypeVOS = baseMapper.selectByCategoryIdAndParams(categoryId, param.getName(), param.getText());
        for (BasicTypeVO basicTypeVO : basicTypeVOS) {
            String jdbcTypeCode = basicTypeVO.getJdbcTypeCode();
            String label = JdbcTypeEnum.getNameByCode(jdbcTypeCode);

            basicTypeVO.setJdbcTypeLabel(label);
        }
        return basicTypeVOS;
    }


    @Override
    public boolean update(BasicType basicType) {
        String name = basicType.getName();
        String text = basicType.getText();
        LocalDateTime updateTime = LocalDateTime.now();
        String updateBy = "admin";
        String categoryId = basicType.getCategoryId();
        basicType.setUpdateTime(updateTime);
        basicType.setUpdateBy(updateBy);

        if (StringUtils.isEmpty(categoryId)) {
            throw new BusinessException("类型分类不可为空");
        }
        boolean exists1 = baseMapper.exists(new LambdaQueryWrapper<BasicType>()
                .eq(BasicType::getName, name).eq(BasicType::getDeleteFlag,DeleteFlagEnum.NO.getCode()).ne(BasicType::getId, basicType.getId()));
        if (exists1) {
            throw new BusinessException("类型名称不能重复");
        }
        boolean exists2 = baseMapper.exists(new LambdaQueryWrapper<BasicType>()
                .eq(BasicType::getText, text).eq(BasicType::getDeleteFlag,DeleteFlagEnum.NO.getCode()).ne(BasicType::getId, basicType.getId()));
        if (exists2) {
            throw new BusinessException("显示名称不能重复");
        }
        return super.updateById(basicType);
    }


    @Override
    public List<TreeNode<String>> findTreeData() {
        // 分类树扁平数据
        List<FeatureCategory> categories = featureCategoryService.findByKind(FeatureKindEnum.basicType.name());

        // 组装树形数据
        List<TreeNode<String>> treeNodeList = categories.stream().map(cate -> {
            TreeNode<String> tn = new TreeNode<>();
            tn.setId(cate.getId());
            tn.setName(cate.getName());
            tn.setText(cate.getName());
            tn.setParentId(cate.getParentId());
            return tn;
        }).collect(Collectors.toList());

        TreeBuilder<TreeNode<String>, String> treeBuilder = new TreeBuilder<>();
        List<TreeNode<String>> treeNodes = treeBuilder.buildTree(treeNodeList);

        List<TreeNode<String>> nodes = new ArrayList<>();
        for (TreeNode<String> treeNode : treeNodes) {
            collectEmptyChildrenNodes(treeNode, nodes);
        }
        List<String> categoryIds = nodes.stream().map(TreeNode::getId).collect(Collectors.toList());
        List<BasicType> basicTypes = baseMapper.selectByCategoryIds(categoryIds);
        Map<String, List<BasicType>> basicTypeGroup = basicTypes.stream().collect(Collectors.groupingBy(BasicType::getCategoryId));

        for (TreeNode<String> node : nodes) {
            String id = node.getId();
            if (basicTypeGroup.containsKey(id)) {
                List<BasicType> bts = basicTypeGroup.get(id);
                List<TreeNode<String>> tns = bts.stream().map(bt -> {
                    TreeNode<String> tn = new TreeNode<>();
                    tn.setId(bt.getId());
                    tn.setName(bt.getName());
                    tn.setText(bt.getText());
                    tn.setParentId(bt.getCategoryId());
                    return tn;
                }).collect(Collectors.toList());

                node.setChildren(tns);
            }
        }
        return treeNodes;
    }


    private void collectEmptyChildrenNodes(TreeNode<String> tn, List<TreeNode<String>> nodes) {
        if (tn.getChildren().isEmpty()) {
            nodes.add(tn);
        } else {
            List<TreeNode<String>> children = tn.getChildren();
            for (TreeNode<String> node : children) {
                collectEmptyChildrenNodes(node, nodes);
            }
        }
    }


    @Override
    public boolean existByCategoryId(String categoryId) {
        Integer exist = baseMapper.existByCategoryId(categoryId);
        return exist != null && exist > 1;
    }

    @Override
    public JSONArray listAllJdbcType() {
        return JdbcTypeEnum.listToJsonArray();
    }

    @Override
    public List<BasicType> findByIds(List<String> ids) {
        LambdaQueryWrapper<BasicType> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BasicType::getDeleteFlag,DeleteFlagEnum.NO.getCode());
        wrapper.in(BasicType::getId, ids);
        return list(wrapper);
    }
}
